//
// Created by LoveHoneyYou on 2024-11-19.
//

#include "TcpServer.h"
#include "TcpConnection.h"
#include <cassert>
#include <netinet/in.h>
#include <sys/socket.h>

TcpServer::TcpServer(unsigned short port, int thread_num)
{
    port_ = port;
    main_loop_ = new EventLoop;
    thread_num_ = thread_num;
    thread_pool_ = new ThreadPool(main_loop_,thread_num_);
    Set_Listen();
}

void TcpServer::Set_Listen()
{
    lfd_ = socket(AF_INET, SOCK_STREAM,0);
    if(lfd_ == -1)
    {
        perror("socket");
        return;
    }

    int opt = 1;
    int ret = setsockopt(lfd_,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof opt);
    if(ret == -1)
    {
        perror("setsockopt");
        return;
    }

    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port_);
    addr.sin_addr.s_addr = INADDR_ANY;
    ret = bind(lfd_,(struct sockaddr*)&addr,sizeof addr);
    if(ret == -1)
    {
        perror("bind");
        return;
    }

    ret = listen(lfd_,128);
    if(ret == -1)
    {
        perror("listen");
    }
}

void TcpServer::Run()
{
    thread_pool_->Run();
    Channel* channel = new Channel(lfd_,FD_Event::ReadEvent,Accept_Connection, nullptr, nullptr,this);
    main_loop_->Add_Task(channel,ElemType::ADD);
    main_loop_->Run();
}

int TcpServer::Accept_Connection(void *arg)
{
    TcpServer* server = (TcpServer*)arg;
    int cfd = accept(server->lfd_,nullptr,nullptr);
    EventLoop* event_loop = server->thread_pool_->Task_Worker_Event_Loop();
    assert(event_loop!=nullptr);
    new TcpConnetion(cfd,event_loop);
    return 0;
}
